<?php
namespace bxd\core\plugin;

/**
 * The MIT License
 *
 * Copyright (c) <year> <copyright holders>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @author Damiano Ciarla
 * @package core
 * @subpackage plugin
 */
class Manager
{
	const PLUGIN_INI_CONFIG = "config.ini";
	
	public function activeAllPlugin()
	{
		// Cartella base dei plugin
		$pluginBasePath = \Bxd::getInstance()->pathApplication . '/' . \Bxd::getInstance()->folderConf()->folder_plugin;
		
		// Percorso dove è presente il file di configurazione
		$configIniPath = $pluginBasePath . '/' . self::PLUGIN_INI_CONFIG;
		
		if(!file_exists($configIniPath))
			throw new exception\PluginException(\Bxd::getInstance()->folderConf()->folder_plugin, exception\PluginException::PLUGIN_NOT_FOUND);
		
		$config = parse_ini_file($configIniPath, true);
		
		foreach($config as $plugin)
		{
			$pluginConfigFile = $pluginBasePath . '/' . $plugin['package'] . '/Config.php';
			
			if(!file_exists($pluginConfigFile))
				throw new exception\PluginException($pluginConfigFile, exception\PluginException::PLUGIN_NOT_FOUND);

			include_once $pluginConfigFile;

			$className = "\\plugin\\" . $plugin['package'] . "\\Config";
			
			try
			{
				$classObject = new $className();
				
				if(!$classObject instanceof config\AbstractConfig)
					throw new exception\PluginException($pluginConfigFile, exception\PluginException::CONFIG_NOT_EXTENDS_THE_CORRECT_CLASS);				
				
				if(!$classObject instanceof config\InterfaceConfig)
					throw new exception\PluginException($pluginConfigFile, exception\PluginException::CONFIG_NOT_IMPLEMENTS_THE_CORRECT_CLASS);
				
				$classObject->setEventOnActivation();
				
				$eventToLaunchTheConfig = $classObject->getEventOnActivation();
				
				if($eventToLaunchTheConfig === null)
				{
					$classObject->runConfiguration();
				}
				else
				{
					\bxd\core\event\Manager::getInstance()->addCallback($eventToLaunchTheConfig, $classObject, "runConfiguration");
				}
			}
			catch(Exception $e)
			{
				throw new exception\PluginException($pluginConfigFile, exception\PluginException::INSTANCED_CLASS_ERROR);				
			}
		}
	}
	
	
	
	
	
//
//	/**
//	 * Lista dei plugin caricati
//	 *
//	 * @var array
//	 */
//	private $_classList = array();
//
//	/**
//	 * Lista dei plugin di default
//	 *
//	 * @var array
//	 */
//	private $_defaultPlugin = array
//	(
//		/**
//		 * Plugin per la gestione delle ACL
//		 */
//		"AclLite" => "acl_lite",
//		
//		/**
//		 * Plugin per la gestione del routing delle URL
//		 */
//		"Router" => "router",
//
//		/**
//		 * Plugin per la registrazione dei log su Database
//		 */
//		"Log" => "log",
//
//		/**
//		 * Plugin per la gestione del modello dei dati
//		 */
//		"EntityManager" => "entity_manager",
//
//		/**
//		 * Plugin per la gestione dei layout dell'applicazione
//		 */
//		"Layout" => "layout"
//	);
//
//	/**
//	 * Classe per l'attivazione dei plugin di default di BXD
//	 *
//	 * @var bxd\core\plugin\res\SystemPlugin
//	 */
//	private $_systemPlugin;
//
//	public function __construct()
//	{
//		// Verifico i plugin presenti nell'applicazione
//		$this->_checkLoaded();
//	}
//
//	public function load($pluginName)
//	{
//		// Verifico se il plugin è stato già caricato all'avvio
//		if(!array_key_exists($pluginName, $this->_classList))
//		{
//			// Verifico se il plugin è presente in quelli di sistema
//			if(array_key_exists($pluginName, $this->_defaultPlugin))
//			{
//				// Costruisco il path dove sono presenti i plugin di BXD
//				$pluginBasePath = str_replace("core", "plugin", \Bxd::getInstance()->pathBxd);
//
//				// Cartella dove sono contenuti i file del plugin
//				$pluginFolder = $this->_defaultPlugin[$pluginName];
//
//				// Costruisco il path della cartella del plugin
//				$pluginPath = $pluginBasePath . '/'. $pluginFolder;
//
//				// Verifico se la cartella esiste
//				if(!is_dir($pluginPath))
//					throw new exception\Plugin(array($pluginFolder, $pluginName), exception\Plugin::BXD_PLUGIN_INCORRECT_PLUGIN_FOLDER);
//
//				// Costruisco il path del file di configurazione del plugin
//				$pluginConfigFile = $pluginBasePath . '/'. $pluginFolder . '/config.php';
//
//				// Verifico se il file di configurazione del plugin esiste
//				if(!file_exists($pluginConfigFile))
//					throw new exception\Plugin($pluginName, exception\Plugin::BXD_PLUGIN_CONFIG_FILE_NOT_FOUND);
//
//				include_once $pluginConfigFile;
//
//				// Creo il nome della classe di configurazione del plugin
//				$className = "Plugin_" . $pluginName;
//
//				if(!class_exists($className))
//					throw new exception\Plugin(array($pluginConfigFile, $className), exception\Plugin::CONFIG_FILES_INCORRECT_DECLARATION_CLASS_NAME);
//
//				$configuration = new $className();
//
//				if(!$configuration instanceof config\AbstractConfig)
//					throw new exception\Plugin($className, exception\Plugin::INVALID_EXTENDS_TYPE_CLASS);
//
//				if(!$configuration instanceof config\InterfaceConfig)
//					throw new exception\Plugin($className, exception\Plugin::INVALID_IMPLEMENTS_TYPE_CLASS);
//
//				$configuration->runConfiguration();
//
//				if($configuration->folder === null || $configuration->folder == "")
//					throw new exception\Plugin("", exception\Plugin::FOLDER_PLUGIN_IS_NOT_SPECIFIED);
//
//				// COPIA DELLE CLASSI DEL PLUGIN
//
//				// Cartella dove sono contenuti i plugin all'interno dell'applicazione
//				$applicationPluginBasePath = \Bxd::getInstance()->pathApplication . '/' . \Bxd::getInstance()->folderConf()->folder_plugin;
//
//				if(!is_writable($applicationPluginBasePath))
//					throw new exception\Plugin($applicationPluginBasePath, exception\Plugin::PLUGIN_FOLDER_IS_NOT_WRITABLE);
//
//				// Path della cartella del plugin per l'applicazione
//				$applicationPluginPath = $applicationPluginBasePath . '/' . $configuration->folder;
//
//				// Path del file di configurazione per l'applicazione
//				$applicationPluginConfigFile = $applicationPluginPath . '/config.php';
//
//				// Creo la cartella del plugin
//				mkdir($applicationPluginPath, 0777, true);
//
//				// Copio il file di configurazione del plugin
//				copy($pluginConfigFile, $applicationPluginConfigFile);
//
//				if(count($configuration->getClassList()))
//				{
//					// Creo la cartella dove saranno inserite le classi del plugin
//					mkdir($applicationPluginPath . '/class', 0777, true);
//
//					foreach($configuration->getClassList() as $className => $classPath)
//					{
//						// Pulisco un eventuale slashes iniziale
//						$classPath = ltrim($classPath, '/');
//
//						// Recupero eventuali cartelle da creare
//						$subFolder = explode("/", $classPath);
//
//						// Verifico se la classe che si sta analizzando è contenuta in una sotto cartella
//						if(count($subFolder) > 1)
//						{
//							// Ricreo il path togliendo il nome del file
//							$subFolder = $applicationPluginPath . '/class/' . implode("/", array_slice($subFolder, 0, -1));
//
//							// Creo la nuova cartella che conterrà la classe che si sta analizzando
//							if(!is_dir($subFolder))
//								mkdir($subFolder, 0777, true);
//						}
//
//						// Copio la classe all'interno del plugin
//						copy($pluginPath . '/class/' . $classPath, $applicationPluginPath . '/class/' . $classPath);
//
//						// Imposto il nome della classe per l'autoload
//						$this->_classList[$pluginName][$className] = $applicationPluginPath . '/class/' . $classPath;
//					}
//				}
//
//				// Aggiungo il plugin al file di configurazione dei plugin dell'applicazione
//				$applicationPluginConf = $applicationPluginBasePath . '/' . self::PLUGIN_INI_CONFIG;
//
//				$fhAppPluginConf = fopen($applicationPluginConf, 'a+');
//				fwrite($fhAppPluginConf, "\n");
//				fwrite($fhAppPluginConf, "[{$pluginName}]\n");
//				fwrite($fhAppPluginConf, "folder = \"{$configuration->folder}\"\n");
//				fclose($fhAppPluginConf);
//
//				// COPIA DEI CONTROLLER DEL PLUGIN
//
//				// Creo il path dove sono contenuti i controller all'interno dell'applicazione
//				$applicationControllerBasePath = \Bxd::getInstance()->pathApplication . '/' . \Bxd::getInstance()->folderConf()->folder_controller;
//
//				// Verifico se il plugin ha bisogno di includere controller all'interno dell'applicazione
//				if(count($configuration->getControllerList()))
//				{
//					// Verifico se la cartella è scrivibile
//					if(!is_writable($applicationControllerBasePath))
//						throw new exception\Plugin($applicationControllerBasePath, exception\Plugin::CONTROLLER_FOLDER_IS_NOT_WRITABLE);
//
//					// Scansiono tutti i controller da integrare nell'applicazione
//					foreach($configuration->getControllerList() as $controller)
//					{
//						// Controllo che il controller sia presente nella cartella del plugin
//						if(!file_exists($pluginPath . '/controller/' . $controller))
//							throw new exception\Plugin(array($controller, $pluginName), exception\Plugin::CONTROLLER_NOT_FOUND_INTO_PLUGIN);
//
//						// Controllo se è già presente lo stesso controller all'interno dell'applicazione
//						if(file_exists($applicationControllerBasePath . '/' . $controller))
//							throw new exception\Plugin($controller, exception\Plugin::CONTROLLER_ALREAD_EXISTS);
//
//						// Verifico la presenza di sottocartelle da creare nell'import del controller
//						if(strpos($controller, "/") !== false)
//						{
//							// Ricavo il path della sottocartella
//							$subfloder = $applicationControllerBasePath . '/' . implode("/", array_slice(explode("/", $controller), 0, -1));
//
//							// Se la cartella non esiste la creo
//							if(!is_dir($subfloder))
//								mkdir($subfloder, 0777, true);
//						}
//
//						// Copio il controller nell'applicazione
//						copy($pluginPath . '/controller/' . $controller, $applicationControllerBasePath . '/' . $controller);
//					}
//				}
//
//				// COPIA DELLE ACTION DEL PLUGIN
//
//				// Creo il path dove sono contenute le view all'interno dell'applicazione
//				$applicationViewBasePath = \Bxd::getInstance()->pathApplication . '/' . \Bxd::getInstance()->folderConf()->folder_view;
//
//				// Verifico se il plugin ha bisogno di includere view all'interno dell'applicazione
//				if(count($configuration->getViewList()))
//				{
//					// Verifico se la cartella è scrivibile
//					if(!is_writable($applicationViewBasePath))
//						throw new exception\Plugin($applicationViewBasePath, exception\Plugin::ACTION_FOLDER_IS_NOT_WRITABLE);
//
//					// Scansiono tutte le view da integrare nell'applicazione
//					foreach($configuration->getViewList() as $view)
//					{
//						// Controllo che la view sia presente nella cartella del plugin
//						if(!file_exists($pluginPath . '/view/' . $view))
//							throw new exception\Plugin(array($view, $pluginName), exception\Plugin::ACTION_NOT_FOUND_INTO_PLUGIN);
//
//						// Controllo se è già presente la stessa view all'interno dell'applicazione
//						if(file_exists($applicationViewBasePath . '/' . $view))
//							throw new exception\Plugin($view, exception\Plugin::ACTION_ALREAD_EXISTS);
//
//						// Verifico la presenza di sottocartelle da creare nell'import del controller
//						if(strpos($view, "/") !== false)
//						{
//							// Ricavo il path della sottocartella
//							$subfloder = $applicationViewBasePath . '/' . implode("/", array_slice(explode("/", $view), 0, -1));
//
//							// Se la cartella non esiste la creo
//							if(!is_dir($subfloder))
//								mkdir($subfloder, 0777, true);
//						}
//
//						// Copio il controller nell'applicazione
//						copy($pluginPath . '/view/' . $view, $applicationViewBasePath . '/' . $view);
//					}
//				}
//
//				// COPIA DEI MEDIA DEL PLUGIN
//
//				// Creo il path dove sono contenute le view all'interno dell'applicazione
//				$applicationWebrootBasePath = \Bxd::getInstance()->pathApplication . '/webroot';
//
//				// Verifico se il plugin ha bisogno di includere view all'interno dell'applicazione
//				if(count($configuration->getMediaList()))
//				{
//					// Verifico se la cartella è scrivibile
//					if(!is_writable($applicationWebrootBasePath))
//						throw new exception\Plugin($applicationWebrootBasePath, exception\Plugin::ACTION_FOLDER_IS_NOT_WRITABLE);
//
//					// Scansiono tutte le view da integrare nell'applicazione
//					foreach($configuration->getMediaList() as $media)
//					{
//						// Controllo che la view sia presente nella cartella del plugin
//						if(!file_exists($pluginPath . '/media/' . $media))
//							throw new exception\Plugin(array($media, $pluginName), exception\Plugin::MEDIA_NOT_FOUND_INTO_PLUGIN);
//
//						// Controllo se è già presente la stessa view all'interno dell'applicazione
//						if(file_exists($applicationWebrootBasePath . '/' . $media))
//							throw new exception\Plugin($media, exception\Plugin::MEDIA_ALREAD_EXISTS);
//
//						// Verifico la presenza di sottocartelle da creare nell'import del controller
//						if(strpos($media, "/") !== false)
//						{
//							// Ricavo il path della sottocartella
//							$subfloder = $applicationWebrootBasePath . '/' . implode("/", array_slice(explode("/", $media), 0, -1));
//
//							// Se la cartella non esiste la creo
//							if(!is_dir($subfloder))
//								mkdir($subfloder, 0777, true);
//						}
//
//						// Copio il controller nell'applicazione
//						copy($pluginPath . '/media/' . $media, $applicationWebrootBasePath . '/' . $media);
//					}
//				}
//			}
//			else throw new exception\Plugin($pluginName, exception\Plugin::PLUGIN_NOT_FOUND);
//		}
//	}
//
//	/**
//	 * Metodo che carica in memoria la lista delle classi per l'autoload del plugin
//	 * specificato nel parametro del metodo
//	 *
//	 * @param string $pluginName Nome del plugin da istanziare
//	 */
//	public function loadPluginClass($pluginName)
//	{
//		if(!array_key_exists($pluginName, $this->_classList))
//			$this->_checkLoaded($pluginName);
//	}
//
//	/**
//	 * Metodo che ritorna la lista dei plugin di default che possono essere inclusi
//	 * nell'applicazione
//	 *
//	 * @return bxd\core\plugin\res\SystemPlugin
//	 */
//	public function activeSystemPlugin()
//	{
//		if ($this->_systemPlugin === null)
//			$this->_systemPlugin = new res\SystemPlugin();
//
//		return $this->_systemPlugin;
//	}
//
//	private function _checkLoaded($pluginToLoad = null)
//	{
//		// Creo il path dove sono contenuti i plugin dell'applicazione
//		$pluginBasePath = \Bxd::getInstance()->pathApplication . '/' . \Bxd::getInstance()->folderConf()->folder_plugin;
//
//		// Se la cartella non esiste viene creata
//		if(!is_dir($pluginBasePath))
//			mkdir($pluginBasePath, 0777);
//
//		// Creo il path per il file di configurazione dei plugin dell'applicazione
//		$confPluginFile = $pluginBasePath . '/' . self::PLUGIN_INI_CONFIG;
//
//		// Verifico se il file esiste. In caso pisitivo viene aperto in lettura altrimenti viene creato
//		if(!file_exists($confPluginFile))
//		{
//			// Verifico se la cartella dei plugin è scrivibile
//			if(!is_writable($pluginBasePath))
//				throw new exception\Plugin(\Bxd::getInstance()->folderConf()->folder_plugin, exception\Plugin::PLUGIN_FOLDER_IS_NOT_WRITABLE);
//
//			$fh = fopen($confPluginFile, 'w+');
//			fclose($fh);
//		}
//		
//		$pluginConfiguration = parse_ini_file($confPluginFile, true);
//		
//		if($pluginToLoad !== null && array_key_exists($pluginToLoad, $pluginConfiguration))
//		{
//			$this->_loadPlugin($pluginToLoad, $pluginConfiguration[$pluginToLoad]);
//		}
//		elseif($pluginToLoad === null)
//		{
//			foreach($pluginConfiguration as $plugin => $info)
//			{
//				$this->_loadPlugin($plugin, $info);
//			}
//		}
//	}
//
//	/**
//	 * Metodo per il caricamento delle classi del plugin
//	 *
//	 * @param string $pluginName Nome del plugin
//	 * @param array $info Lista delle informazioni del plugin
//	 */
//	private function _loadPlugin($pluginName, array $info)
//	{
//		$pluginFolder = $info['folder'];
//
//		// Se nel file di configurazione dei plugin è abilitato l'autoload o se il nome del plugin compare tra quelli impostati per essere caricati
//		// all'avvio o se è stato esplicitato di caricare questo plugin proseguo al suo caricamento
//		if(\Bxd::getInstance()->pluginConf()->autoloadExistPlugin || in_array($pluginName, \Bxd::getInstance()->pluginConf()->getPluginToAutoload()) || $pluginToLoad !== null)
//		{
//			// Creo il path dove sono contenuti i plugin dell'applicazione
//			$pluginBasePath = \Bxd::getInstance()->pathApplication . '/' . \Bxd::getInstance()->folderConf()->folder_plugin;
//
//			// Costruisco il path della cartella che contiene il plguin
//			$pluginPath = $pluginBasePath . '/'. $pluginFolder;
//
//			// Verifico se la cartella esiste
//			if(!is_dir($pluginPath))
//				throw new exception\Plugin(array($pluginFolder, $pluginName), exception\Plugin::APPLICATION_PLUGIN_INCORRECT_PLUGIN_FOLDER);
//
//			// Costruisco il path per la classe di configurazione del plugin
//			$pluginConfigFile = $pluginBasePath . '/'. $pluginFolder . '/config.php';
//
//			// Verifico se il file esiste
//			if(!file_exists($pluginConfigFile))
//				throw new exception\Plugin($pluginName, exception\Plugin::APPLICATION_PLUGIN_CONFIG_FILE_NOT_FOUND);
//
//			include_once $pluginConfigFile;
//
//			// Creo il nome della classe di configurazione del plugin
//			$className = "Plugin_" . $pluginName;
//
//			// Verifico se il nome della classe è scritto correttamente
//			if(!class_exists($className))
//				throw new exception\Plugin(array($pluginConfigFile, $className), exception\Plugin::CONFIG_FILES_INCORRECT_DECLARATION_CLASS_NAME);
//
//			$configuration = new $className();
//
//			if(!$configuration instanceof config\AbstractConfig)
//				throw new exception\Plugin($className, exception\Plugin::INVALID_EXTENDS_TYPE_CLASS);
//
//			if(!$configuration instanceof config\InterfaceConfig)
//				throw new exception\Plugin($className, exception\Plugin::INVALID_IMPLEMENTS_TYPE_CLASS);
//
//			$configuration->runConfiguration();
//
//			// Scansioni tutte le classe dichiarate nella configurazione e le inserisco nell'array
//			// della classi su cui l'autoload può far riferimento
//			foreach($configuration->getClassList() as $className => $classPath)
//				$this->_classList[$pluginName][$className] = $pluginPath . '/class/' . $classPath;
//		}
//	}
	
	
}
?>
